package nape.phys;
import nape.util.FastMath;
import nape.util.MixPool;
import nape.util.Names;
import nape.util.NpAlgorithm;
import nape.util.NpList;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Shape;
import nape.util.NpNode_ZNContact;
import nape.util.NpAllocList_ZNContact;
import nape.util.NpNode_ZNV2;
import nape.util.NpList_ZNV2;
import nape.util.NpNode_Vec2__Dynamic;
import nape.util.NpList_Vec2__Dynamic;
import nape.util.NpNode_ZNShp;
import nape.util.NpList_ZNShp;

//'newfile' generated imports
import nape.util.NpList_ZNShp;







class Material {
    public var znp_inner:ZNMat;
    
    public function new(?elasticity:Float=0.0, ?dynamicFriction:Float=1.0, ?staticFriction:Float=2.0, ?density:Float=0.001) {
        znp_inner = new ZNMat(elasticity, dynamicFriction, staticFriction, density);
        znp_inner.outer = this;
    }
    
    public var dynamicFriction(get_dynamicFriction,set_dynamicFriction):Float;
    public var staticFriction (get_staticFriction, set_staticFriction ):Float;
    public var elasticity     (get_elasticity,     set_elasticity     ):Float;
    public var density        (get_density,        set_density        ):Float;
    
    public function get_dynamicFriction() return znp_inner.dynamicFriction
    public function get_staticFriction () return znp_inner.staticFriction
    public function get_elasticity     () return znp_inner.elasticity
    public function get_density        () return znp_inner.density
    
    public function set_dynamicFriction(dynamicFriction:Float) {
        if(dynamicFriction>=0.0 && dynamicFriction!=znp_inner.dynamicFriction) {
            znp_inner.dynamicFriction = dynamicFriction;
            znp_inner.invalidate(ZNMat.WAKE|ZNMat.ANGDRAG);
        }
        return znp_inner.dynamicFriction;
    }
    
    public function set_staticFriction(staticFriction:Float) {
        if(staticFriction>=0.0 && staticFriction!=znp_inner.staticFriction) {
            znp_inner.staticFriction = staticFriction;
            znp_inner.invalidate(ZNMat.WAKE);
        }
        return znp_inner.staticFriction;
    }
    
    public function set_elasticity(elasticity:Float) {
        if(elasticity>=0.0 && elasticity!=znp_inner.elasticity) {
            znp_inner.elasticity = elasticity;
            znp_inner.invalidate(0);
        }
        return znp_inner.elasticity;
    }
    
    public function set_density(density:Float) {
        if(density>=0.0 && density!=znp_inner.elasticity) {
            znp_inner.density = density;
            znp_inner.invalidate(ZNMat.WAKE|ZNMat.PROPS);
        }
        return znp_inner.density;
    }
    
    public inline function toString() {
        return "{ elasticity: "+elasticity
               +" dynamicFriction: "+dynamicFriction
               +" staticFriction: "+staticFriction
               +" density: "+density
               +" }";
    }
    
    public var shapes(get_shapes,never):ShapeIterator;
    
    public inline function get_shapes() {
        return ShapeIterator.get(znp_inner.shapes);
    }
}

class ZNMat {
    public var outer:Material;
    
    public var shapes:NpList_ZNShp;
    
    
    public var dynamicFriction:Float;
    public var staticFriction:Float;
    public var density:Float;
    public var elasticity:Float;

    
    public function new(elasticity:Float, dynamicFriction:Float, staticFriction:Float, density:Float) {
        this.dynamicFriction = dynamicFriction;
        this.staticFriction = staticFriction;
        this.density = density;
        this.elasticity = elasticity;
        
        shapes = new NpList_ZNShp();
    }
    
    
    public inline function addShape(shape:ZNShp) {
        shapes.add(shape);
    }
    
    
    public inline function remShape(shape:ZNShp) {
        shapes.remove(shape);
    }
    
    public static inline var WAKE:Int = 1;
    public static inline var ANGDRAG:Int = 2;
    public static inline var PROPS:Int = 3;
    
    public inline function invalidate(x:Int) {
          {
    var npiterator = shapes.begin();
    while(npiterator != null) {
        var s = npiterator.elem();
        {
            
            
            s.invalidate_material(x);
        }
        npiterator = npiterator.next;
    }
};
    }
}
